package org.mat.framework.service.context;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import org.apache.commons.lang3.StringUtils;
import org.mat.framework.core.context.RequestContext;
import org.mat.framework.core.context.RequestContextConstants;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import lombok.extern.slf4j.Slf4j;
import org.mat.framework.core.context.RequestContextUtils;
import org.mat.framework.util.JacksonUtils;
import org.slf4j.MDC;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * @ClassName: FeignClientRequestInterceptor
 * @Date: 2021/8/17
 * @author: sunxinhe
 * @Version: 1.0
 * @Description: TODO
 */
@Slf4j
public class RequestContextFeignClientInterceptor implements RequestInterceptor {

    @Override
    public void apply(RequestTemplate requestTemplate) {

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        Enumeration<String> headerNames = request.getHeaderNames();
        if (headerNames != null) {
            while (headerNames.hasMoreElements()) {
                String name = headerNames.nextElement();
                //TODO 后续考虑划定一个范围统一传递，全部复制可能不太好
                if (name == null || name.equalsIgnoreCase("content-length")) {
                    continue;
                }
                String values = request.getHeader(name);
                requestTemplate.header(name, values);
            }
        }

        // 复制queries
        Map<String, Collection<String>> queries = new HashMap<>();

        Map<String, String[]> parameterMap = request.getParameterMap();
        if (parameterMap != null && parameterMap.size() > 0) {
            for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
                String key = entry.getKey();
                if (requestTemplate.queries().get(key) != null) {
                    continue;
                }
                String[] value = entry.getValue();
                if (value != null && value.length > 0) {
                    Collection<String> values = new ArrayList<>();
                    for (String s : value) {
                        values.add(s);
                    }
                    queries.put(key, values);
                }
            }
            requestTemplate.queries(queries);
        }


        //region 复制RequestContext内容
        // 复制traceId
        String traceId = MDC.get(RequestContextConstants.TRACE_ID_KEY_FOR_MDC);
        log.info("set traceId for feign request: url = {}, traceId = {} ", requestTemplate.url(), traceId);
        requestTemplate.header(RequestContextConstants.TRACE_ID_KEY_FOR_HTTP_HEADER, traceId);

        // 复制基础信息
        RequestContext requestContext = RequestContextUtils.get();
        Boolean debugEnabled = requestContext.getDebugEnabled();
        if (debugEnabled != null) {
            requestTemplate.header(RequestContextConstants.DEBUG_ENABLED_KEY_FOR_HTTP_HEADER, String.valueOf(debugEnabled));
        }


        Long startTime = requestContext.getStartTime();
        if (startTime != null) {
            requestTemplate.header(RequestContextConstants.START_TIME_KEY_FOR_HTTP_HEADER, String.valueOf(startTime));
        }

        // 复制data
        Map<String, String> requestContextData = requestContext.getData();
        if (requestContextData != null && !requestContextData.isEmpty()) {
            for (Map.Entry<String, String> entry : requestContextData.entrySet()) {
                if (entry.getKey() != null && entry.getValue() != null) {
                    requestTemplate.header(entry.getKey(), entry.getValue());
                }
            }
        }

        //endregion


//        // 传递用户信息请求头，防止丢失
//        String userId = request.getHeader(SecurityConstants.DETAILS_USER_ID);
//        if (StringUtils.isNotEmpty(userId))
//        {
//            requestTemplate.header(SecurityConstants.DETAILS_USER_ID, userId);
//        }
//        String userKey = request.getHeader(SecurityConstants.USER_KEY);
//        if (StringUtils.isNotEmpty(userKey))
//        {
//            requestTemplate.header(SecurityConstants.USER_KEY, userKey);
//        }
//        String userName = request.getHeader(SecurityConstants.DETAILS_USERNAME);
//        if (StringUtils.isNotEmpty(userName))
//        {
//            requestTemplate.header(SecurityConstants.DETAILS_USERNAME, userName);
//        }
//        String authentication = request.getHeader(SecurityConstants.AUTHORIZATION_HEADER);
//        if (StringUtils.isNotEmpty(authentication))
//        {
//            requestTemplate.header(SecurityConstants.AUTHORIZATION_HEADER, authentication);
//        }
    }

}
